﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections.Specialized;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Collections;

namespace Autorun
{
	public partial class TaskDialog : Form
	{
		private TaskConfigurationItem _item;
		private ServerManagement _proxy;

		public TaskDialog()
		{
			InitializeComponent();
		}

		public void SetData(ServerManagement proxy, int recordId)
		{
			_proxy = proxy;

			_item = _proxy.Configuration.Tasks.GetTaskInformation(recordId);
			txtCaption.Text = _item.Caption;
			myProperties.SelectedObject = BuildParametersFacade(_item.Parameters);
		}

		#region "Facade Builder for the Parameters Property"
		private StringDictionary BuildParametersFacade(StringDictionary parameters)
		{
			StringDictionary rc;
			StringBuilder source;
			StringBuilder constructor;
			CSharpCodeProvider codeProvider;
			CompilerParameters compilerParameters;
			CompilerResults compilerResults;

			// ===============================================================
			// === Pre-Process                                             ===
			// ===============================================================
			source = new StringBuilder();
			constructor = new StringBuilder();
			codeProvider = new CSharpCodeProvider();
			compilerParameters = new CompilerParameters();

			// ===============================================================
			// === Process                                                 ===
			// ===============================================================
			// Prepare the construction definition
			constructor.AppendLine("public ParametersFacade() : base()");
			constructor.AppendLine("{");

			// Declare Namespace and usings
			source.AppendLine("using System;");
			source.AppendLine("using System.Collections.Specialized;");
			source.AppendLine("using System.ComponentModel;");
			source.AppendLine("namespace Autorun");
			source.AppendLine("{"); // Begin "namespace"

			// Declare class
			source.AppendLine("[Serializable]");
			source.AppendLine("public class ParametersFacade : StringDictionary");
			source.AppendLine("{"); // Begin "class"

			foreach (DictionaryEntry item in parameters)
				AddPropertyToFacade(source, constructor, item.Key.ToString(), item.Value.ToString());

			// Terminate the constructor definition and add it to the class
			constructor.AppendLine("}");
			source.AppendLine(constructor.ToString());

			// Terminate the class and the namespace
			source.AppendLine("}"); // End "class"
			source.AppendLine("}"); // End "namespace"

			compilerParameters.ReferencedAssemblies.Add("System.dll");
			compilerParameters.GenerateExecutable = false;
			compilerParameters.GenerateInMemory = true;

			System.Diagnostics.Debug.WriteLine(source.ToString());
			compilerResults = codeProvider.CompileAssemblyFromSource(compilerParameters, source.ToString());
			if (compilerResults.Errors.Count != 0)
			{
				source = new StringBuilder();
				foreach (CompilerError item in compilerResults.Errors)
					source.AppendLine(item.ToString());
				System.Windows.Forms.MessageBox.Show("Test");
				MessageBox.Show(source.ToString());
				compilerResults = null;
				rc = null;
			}
			else
				rc = (StringDictionary)compilerResults.CompiledAssembly.CreateInstance("Autorun.ParametersFacade");

			return rc;
		}

		private void AddPropertyToFacade(StringBuilder source, StringBuilder constructor, string name, string defaultValue)
		{
			source.AppendLine("[Category(\"Configuration\")]");
			source.AppendFormat("\npublic string {0}", name);
			source.AppendLine("{");
			source.AppendLine("get");
			source.AppendLine("{");
			source.AppendFormat("\nif (this.ContainsKey(\"{0}\") == false)", name);
			source.AppendFormat("\nreturn \"{0}\";", defaultValue.Replace("\\", "\\\\"));
			source.AppendLine("else");
			source.AppendFormat("\nreturn this[\"{0}\"];", name);
			source.AppendLine("}");
			source.AppendLine("set");
			source.AppendLine("{");
			source.AppendFormat("\nthis[\"{0}\"] = value;", name);
			source.AppendLine("}");
			source.AppendLine("}");

			constructor.AppendFormat("\nthis[\"{0}\"] = \"{1}\";", name, defaultValue.Replace("\\", "\\\\"));
		}

		#endregion

		private void btOK_Click(object sender, EventArgs e)
		{
			StringDictionary parmIn;
			StringDictionary parmOut;

			if (txtCaption.Text.Length != 0)
			{
				_item.Caption = txtCaption.Text;

				// I cannot send directly the facade because it exists in a private assembly
				// that is unknown by the framework. I Simply transfer the parameters from
				// the inherited StringDictionary to a normal StringDictionary object.
				parmIn = (StringDictionary)myProperties.SelectedObject;
				parmOut = new StringDictionary();
				foreach (DictionaryEntry item in parmIn)
					parmOut.Add(item.Key.ToString(), item.Value.ToString());
				_item.Update(parmOut);
				DialogResult = DialogResult.OK;
			}
		}
	}
}
